package com.bah.tract.client.ui;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.UUID;

import javax.swing.DefaultCellEditor;
import javax.swing.JDialog;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.WebServiceException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bah.tract.client.ErrorHandler;
import com.bah.tract.client.Timer;
import com.bah.tract.client.cache.je.WorkCache;
import com.bah.tract.client.ui.ProjectComboModel.ProjectLabel;
import com.bah.tract.client.ui.TaskComboModel.TaskLabel;
import com.bah.tract.client.workstore.TaskProvider;
import com.bah.tract.client.workstore.TaskProviderFactory;
import com.bah.tract.service.Project;
import com.bah.tract.service.ProjectList;
import com.bah.tract.service.ProjectService;
import com.bah.tract.service.Task;
import com.bah.tract.service.TractServiceException_Exception;
import com.bah.tract.service.Work;
import com.bah.tract.service.WorkService;
import com.bah.tract.service.WorkStore;
import com.google.inject.Inject;

/**
 * @author 524506
 */
public class TaskEntryForm extends JDialog {

	private static final Logger LOG = LoggerFactory
			.getLogger(TaskEntryForm.class);

	private final ProjectService mProjectService;

	private final WorkService mWorkService;

	/**
	 * @uml.property name="mTimer"
	 * @uml.associationEnd
	 */
	private final Timer mTimer;

	/**
	 * @uml.property name="mWorkCache"
	 * @uml.associationEnd
	 */
	private final WorkCache mWorkCache;

	/**
	 * @uml.property name="mTaskProviderFactory"
	 * @uml.associationEnd
	 */
	private final TaskProviderFactory mTaskProviderFactory;

	/**
	 * @uml.property name="mTolPropertiesDialog"
	 * @uml.associationEnd
	 */
	private final TOLPropertiesDialog mTolPropertiesDialog;

	@Inject
	public TaskEntryForm(final ProjectService projectService,
			final WorkService workService, final Timer timer,
			final WorkCache workCache,
			final TaskProviderFactory taskProviderFactory,
			final TOLPropertiesDialog tolPropertiesDialog) {
		mTolPropertiesDialog = tolPropertiesDialog;
		mTaskProviderFactory = taskProviderFactory;
		mWorkCache = workCache;
		mProjectService = projectService;
		mTimer = timer;
		mWorkService = workService;
		setTitle("TRACT - Task Selection");
		final Image image = Toolkit.getDefaultToolkit().getImage(
				"stopwatch.PNG");
		setIconImage(image);
		add(new TaskPanel());
		pack();
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * @author 524506
	 */
	private class TaskPanel extends javax.swing.JPanel {

		private final class TaskStartedListener implements ActionListener {
			@Override
			public void actionPerformed(final ActionEvent e) {
				final Project project = ((ProjectLabel) projectBox
						.getSelectedItem()).getProject();
				LOG.debug("Starting work on {}", project.getLabel());
				// loop through the rows of the table to identify tasks
				final TableModel model = taskTable.getModel();
				boolean close = true;
				final Work work = new Work();

				for (int i = 0; i < model.getRowCount(); i++) {
					final Boolean required = (Boolean) model.getValueAt(i,
							1);
					final TaskLabel taskLabel = (TaskLabel) model
							.getValueAt(i, 2);
					if (taskLabel == null) {
						if (required) {
							LOG.error("A task for {} is required.",
									model.getValueAt(i, 0));
							close = false;
						}
					} else {
						work.getTasks().add(taskLabel.getTask());
					}
				}
				if (close) {

					work.setComment(comment.getText());
					work.setProjectId(project.getId());
					work.setGUID(UUID.randomUUID().toString());
					final GregorianCalendar c = new GregorianCalendar();
					try {
						final XMLGregorianCalendar date = DatatypeFactory
								.newInstance().newXMLGregorianCalendar(c);
						work.setStart(date);
						// Don't set the end time now.
						mWorkService.logWork(work);
						mTimer.setState(true);
					} catch (final DatatypeConfigurationException ex) {
						ErrorHandler.handleError(ex);
					} catch (final TractServiceException_Exception ex) {
						ErrorHandler.handleError(ex);
					}
					TaskEntryForm.this.setVisible(false);
				}
			}
		}

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		/** Creates new form NewJPanel2 */
		public TaskPanel() {
			initComponents();
		}

		/**
		 * This method is called from within the constructor to initialize the
		 * form. WARNING: Do NOT modify this code. The content of this method is
		 * always regenerated by the Form Editor.
		 */
		// <editor-fold defaultstate="collapsed" desc="Generated Code">
		private void initComponents() {
			projectLabel = new javax.swing.JLabel();
			projectBox = new javax.swing.JComboBox();
			commentLabel = new javax.swing.JLabel();
			comment = new javax.swing.JTextField();
			jScrollPane1 = new javax.swing.JScrollPane();
			taskTable = new TaskTable();
			cancel = new javax.swing.JButton();
			ok = new javax.swing.JButton();

			setName("Form"); // NOI18N

			final ResourceBundle resourceMap = ResourceBundle
					.getBundle("com.bah.tract.client.ui.TaskEntry");
			projectLabel.setText(resourceMap.getString("jLabel1.text")); // NOI18N
			projectLabel.setName("jLabel1"); // NOI18N

			Work work = mWorkCache.get("current");
			if (work == null) {
				work = mWorkCache.get("last");
			}
			selectProject(work);
			final ProjectLabel selectedProject = ((ProjectLabel) projectBox
					.getSelectedItem());
			if (selectedProject != null) {
				populateTaskForm(
						((ProjectLabel) projectBox.getSelectedItem())
								.getProject(),
						work);
			}
			projectBox.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(final ActionEvent e) {
					populateTaskForm(((ProjectLabel) projectBox
							.getSelectedItem()).getProject(), null);
				}
			});
			projectBox.setName("jComboBox1"); // NOI18N

			commentLabel.setText(resourceMap.getString("jLabel2.text")); // NOI18N
			commentLabel.setName("jLabel2"); // NOI18N

			comment.setText(resourceMap.getString("jTextField1.text")); // NOI18N
			comment.setName("jTextField1"); // NOI18N

			jScrollPane1.setName("jScrollPane1"); // NOI18N

			jScrollPane1.setViewportView(taskTable);

			cancel.setText(resourceMap.getString("jButton1.text")); // NOI18N
			cancel.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(final ActionEvent e) {
					TaskEntryForm.this.setVisible(false);
				}
			});
			cancel.setName("jButton1"); // NOI18N

			ok.setText(resourceMap.getString("jButton2.text")); // NOI18N
			ok.addActionListener(new TaskStartedListener());
			ok.setName("ok"); // NOI18N
			taskTable.setName("taskTable");

			final javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
					this);
			setLayout(layout);
			layout.setHorizontalGroup(layout
					.createParallelGroup(
							javax.swing.GroupLayout.Alignment.LEADING)
					.addGroup(
							javax.swing.GroupLayout.Alignment.TRAILING,
							layout.createSequentialGroup()
									.addContainerGap()
									.addGroup(
											layout.createParallelGroup(
													javax.swing.GroupLayout.Alignment.TRAILING)
													.addComponent(
															jScrollPane1,
															javax.swing.GroupLayout.Alignment.LEADING,
															javax.swing.GroupLayout.DEFAULT_SIZE,
															613,
															Short.MAX_VALUE)
													.addGroup(
															layout.createSequentialGroup()
																	.addComponent(
																			projectLabel)
																	.addPreferredGap(
																			javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
																	.addComponent(
																			projectBox,
																			javax.swing.GroupLayout.PREFERRED_SIZE,
																			209,
																			javax.swing.GroupLayout.PREFERRED_SIZE)
																	.addGap(18,
																			18,
																			18)
																	.addComponent(
																			commentLabel)
																	.addPreferredGap(
																			javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
																	.addComponent(
																			comment,
																			javax.swing.GroupLayout.DEFAULT_SIZE,
																			287,
																			Short.MAX_VALUE))
													.addGroup(
															layout.createSequentialGroup()
																	.addComponent(
																			ok)
																	.addPreferredGap(
																			javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
																	.addComponent(
																			cancel)))
									.addContainerGap()));
			layout.setVerticalGroup(layout
					.createParallelGroup(
							javax.swing.GroupLayout.Alignment.LEADING)
					.addGroup(
							layout.createSequentialGroup()
									.addContainerGap()
									.addGroup(
											layout.createParallelGroup(
													javax.swing.GroupLayout.Alignment.BASELINE)
													.addComponent(projectLabel)
													.addComponent(
															projectBox,
															javax.swing.GroupLayout.PREFERRED_SIZE,
															javax.swing.GroupLayout.DEFAULT_SIZE,
															javax.swing.GroupLayout.PREFERRED_SIZE)
													.addComponent(commentLabel)
													.addComponent(
															comment,
															javax.swing.GroupLayout.PREFERRED_SIZE,
															javax.swing.GroupLayout.DEFAULT_SIZE,
															javax.swing.GroupLayout.PREFERRED_SIZE))
									.addGap(18, 18, 18)
									.addComponent(
											jScrollPane1,
											javax.swing.GroupLayout.DEFAULT_SIZE,
											226, Short.MAX_VALUE)
									.addGap(18, 18, 18)
									.addGroup(
											layout.createParallelGroup(
													javax.swing.GroupLayout.Alignment.BASELINE)
													.addComponent(cancel)
													.addComponent(ok))
									.addContainerGap()));

		}// </editor-fold>

		// Variables declaration - do not modify
		private javax.swing.JButton cancel;
		private javax.swing.JButton ok;
		private javax.swing.JComboBox projectBox;
		private javax.swing.JLabel projectLabel;
		private javax.swing.JLabel commentLabel;
		private javax.swing.JScrollPane jScrollPane1;
		/**
		 * @uml.property name="taskTable"
		 * @uml.associationEnd
		 */
		private TaskTable taskTable;
		private javax.swing.JTextField comment;

		// End of variables declaration

		private void selectProject(final Work work) {
			Project project = null;
			try {
				final ProjectList projectList = mProjectService
						.getAllProjects();
				final ProjectComboModel model = new ProjectComboModel(
						projectList);
				projectBox.setModel(model);
				if (work != null) {
					for (final Project p : projectList.getProject()) {
						if (p.getId() == work.getProjectId()) {
							project = p;
						}
					}
					if (project != null) {
						projectBox.setSelectedItem(model.new ProjectLabel(
								project));
					}
				}
			} catch (final TractServiceException_Exception e) {
				ErrorHandler.handleError(e);
			} catch (final WebServiceException e) {
				ErrorHandler.handleError(e);
			}
		}

		private void populateTaskForm(final Project project, final Work work) {
			try {
				final List<WorkStore> workStores = mProjectService
						.getProjectStores(project.getId()).getWorkStore();
				final int size = workStores.size();
				final Object[][] data = new Object[size][3];
				for (int i = 0; i < size; i++) {
					data[i][0] = workStores.get(i).getLabel();
					data[i][1] = workStores.get(i).isRequired();
					data[i][2] = null;
				}
				taskTable
						.setModel(new javax.swing.table.DefaultTableModel(
								data,
								new String[] { "Work Store", "Required", "Task" }));
				final Map<Long, Task> taskMap = new HashMap<Long, Task>();
				if (work != null) {
					for (final Task t : work.getTasks()) {
						taskMap.put(t.getStoreId(), t);
					}
				}
				for (int i = 0; i < size; i++) {
					final WorkStore store = workStores.get(i);
					final TaskProvider taskProvider = mTaskProviderFactory
							.getTaskProvider(store);
					final MyComboBoxRenderer taskRenderer = new MyComboBoxRenderer();
					final TaskComboModel taskModel = new TaskComboModel(
							taskProvider.getTasks());
					if (taskMap.containsKey(store.getId())) {
						final TaskLabel taskLabel = taskModel.new TaskLabel(
								taskMap.get(store.getId()));
						taskTable.setValueAt(taskLabel, i, 2);
					}
					taskRenderer.setModel(taskModel);
					final DefaultCellEditor cellEditor = new DefaultCellEditor(
							taskRenderer);
					taskTable.setTaskEditor(i, cellEditor);
					taskTable.setTaskRenderer(i, taskRenderer);

				}
				taskTable.addMouseListener(new TaskPropertiesMouseAdapter(
						mTolPropertiesDialog, taskTable));
				final TableColumn column = taskTable.getColumnModel()
						.getColumn(1);
				column.setCellRenderer(new MyCheckBoxRenderer());

			} catch (final TractServiceException_Exception e) {
				ErrorHandler.handleError(e);
			}
		}
	}
}
